package com.ydl.shopping.exception;

import com.ydl.shopping.core.enums.ResultEnum;
import com.ydl.shopping.core.vo.ResultVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局异常处理器
 *
 * @author 林武泰
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(ServiceException.class)
    public ResultVO serviceException(ServiceException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("业务异常, 请求地址'{}'", requestURI, e);
        return new ResultVO(e.getCode(), null, e.getMessage());
    }

    /**
     * 参数校验异常
     */
    @ExceptionHandler(BindException.class)
    public ResultVO bindException(BindException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        log.error("参数校验异常, 请求地址'{}'：{}", requestURI, objectError.getDefaultMessage());
        return ResultVO.error(objectError.getDefaultMessage());
    }

    @ExceptionHandler(UsernameNotFoundException.class)
    public ResultVO usernameNotFoundException(UsernameNotFoundException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("用户名称异常, 请求地址'{}'：{}", requestURI, e.getMessage());
        return ResultVO.error(e.getMessage());
    }

    /** 方法请求异常 */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultVO httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("方法请求异常, 请求地址'{}'：{}", requestURI, e.getMessage());
        return ResultVO.resultEnum(ResultEnum.NOT_IMPLEMENTED);
    }

    /**
     * 运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public ResultVO doException(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("运行时异常, 请求地址'{}'", requestURI, e);
        return ResultVO.error(e.getMessage());
    }

    /**
     * 外键约束异常
     */
    @ExceptionHandler(value = DataAccessException.class)
    public ResultVO handleSqlIntegrityConstraintViolationException(DataAccessException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        if (e instanceof DataIntegrityViolationException) {
            log.error("请求地址'{}',发生SQL外键约束异常", requestURI, e);
            return ResultVO.error("外键约束绑定，操作失败");
        }
        log.error("请求地址'{}',发生SQL异常", requestURI, e);
        return ResultVO.error("SQL异常，操作失败");
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public ResultVO handleException(Exception e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生系统异常", requestURI, e);
        return ResultVO.error(e.getMessage());
    }
}
